package db

import (
	"fmt"

	"github.com/xujiajun/nutsdb"
	"lucidity.note/app/common/logger"
)

type DiskIndexConn struct {
	// 磁盘的索引模式：数据持久话在磁盘的数据文件中，数据持久化
	DB *nutsdb.DB
}

// 插入数据or更新数据，持久化到数据文件中
// @param bucket {string} 数据桶，类似与关系型数据库中的表
// @param key {string} 键
// @param value {string} 数据值
func (conn *DiskIndexConn) Insert(bucket, key, value string) error {
	err := conn.DB.Update(func(tx *nutsdb.Tx) error {
		if err := tx.Put(bucket, []byte(key), []byte(value), nutsdb.Persistent); nil != err {
			logger.FAULT.Printf(fmt.Sprintf("磁盘索引模式-插入数据失败{bucket=%s, key=%s, value=%s}: %s\r\n", bucket, key, value, err.Error()))
			return err
		}
		return nil
	})
	return err
}

// 更新数据，持久化到数据文件中
// @param bucket {string} 数据桶，类似与关系型数据库中的表
// @param key {string} 键
// @param value {string} 数据值x
func (conn *DiskIndexConn) Update(bucket, key, value string) error {
	err := conn.DB.Update(func(tx *nutsdb.Tx) error {
		if err := tx.Put(bucket, []byte(key), []byte(value), nutsdb.Persistent); nil != err {
			logger.FAULT.Printf(fmt.Sprintf("磁盘索引模式-更新数据失败{bucket=%s, key=%s, value=%s}: %s\r\n", bucket, key, value, err.Error()))
			return err
		}
		return nil
	})
	return err
}

// 查询数据
// @param bucket {string} 数据桶，类似与关系型数据库中的表
// @param key {string} 键
func (conn *DiskIndexConn) Select(bucket, key string) (value string, err error) {
	err = conn.DB.View(func(tx *nutsdb.Tx) error {
		if e, err := tx.Get(bucket, []byte(key)); nil != err {
			logger.FAULT.Printf(fmt.Sprintf("磁盘索引模式-查询数据失败{bucket=%s, key=%s}: %s\r\n", bucket, key, err.Error()))
			return err
		} else {
			value = string(e.Value)
		}
		return nil
	})
	return value, err
}

// 删除数据
// @param bucket {string} 数据桶，类似与关系型数据库中的表
// @param key {string} 键
func (conn *DiskIndexConn) Delete(bucket, key string) error {
	err := conn.DB.Update(func(tx *nutsdb.Tx) error {
		if err := tx.Delete(bucket, []byte(key)); nil != err {
			logger.FAULT.Printf(fmt.Sprintf("磁盘索引模式-删除数据失败{bucket=%s, key=%s}: %s\r\n", bucket, key, err.Error()))
			return err
		}
		return nil
	})
	return err
}

// 删除数据桶
// @param bucket {string} 数据桶，类似与关系型数据库中的表
func (conn *DiskIndexConn) DeleteBucket(bucket string) error {
	err := conn.DB.Update(func(tx *nutsdb.Tx) error {
		if err := tx.DeleteBucket(nutsdb.DataStructureBPTree, bucket); nil != err {
			logger.FAULT.Printf(fmt.Sprintf("磁盘索引模式-删除数据桶失败{bucket=%s}: %s\r\n", bucket, err.Error()))
			return err
		}
		return nil
	})
	return err
}

// 获取桶中所有键值
// @param bucket {string} 数据桶，类似与关系型数据库中的表
// @return entries {[]map[string]string} 切片Map，mapkey=>key, mapvalue=> value
func (conn *DiskIndexConn) GetAll(bucket string) (entries map[string]string, e error) {
	entries = make(map[string]string)
	err := conn.DB.View(func(tx *nutsdb.Tx) error {
		if es, err := tx.GetAll(bucket); nil != err {
			logger.FAULT.Printf(fmt.Sprintf("磁盘索引模式-获取桶中所有键值失败{bucket=%s}: %s\r\n", bucket, err.Error()))
			return err
		} else {
			for _, elem := range es {
				var key = string(elem.Key)
				var value = string(elem.Value)
				entries[key] = value
			}
		}
		return nil
	})
	return entries, err
}
